package com.krafteapps.androidsecurehttpclient.example;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLException;

import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.util.EntityUtils;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;

import com.krafteapps.androidsecurehttpclient.AndroidSecureHttpClient;
import com.krafteapps.androidsecurehttpclient.HttpTrustManager;
import com.krafteapps.androidsecurehttpclient.HttpTrustManager.CertificateNotAcceptedException;
import com.krafteapps.androidsecurehttpclient.R;

public class AndroidSecureHttpClientExampleActivity extends Activity {
	private View mViewComplete;
	private View mViewLoading;
	
	private LoadUrlAsyncTask mLoadUrlTask;
	
	private enum LayoutState {
		NONE, LOADING, COMPLETE
	};
	private LayoutState mLayoutState = LayoutState.NONE;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mViewComplete = findViewById(R.id.layout_complete);
        mViewLoading = findViewById(R.id.layout_loading);
        
        findViewById(R.id.buttonGo).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (mLoadUrlTask!=null && mLayoutState==LayoutState.LOADING)
					mLoadUrlTask.cancel(true);
				mLoadUrlTask = new LoadUrlAsyncTask();
				
				final String url = ((TextView)findViewById(R.id.textUrl)).getText().toString();
				
				try {
					if (((CheckBox)findViewById(R.id.checkSecure)).isChecked())
						mLoadUrlTask.execute(AndroidSecureHttpClient.newInstance(getApplicationContext(), true), url);
					else
						mLoadUrlTask.execute(AndroidSecureHttpClient.newInstance(getApplicationContext(), false), url);
				} catch (CertificateException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
        });
        
        findViewById(R.id.buttonClearKeystore).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				HttpTrustManager.clearKeyStore(getApplicationContext());	
			}
        });
        
        LayoutState layoutState = LayoutState.NONE;
        if (savedInstanceState!=null) {
        	final LayoutState[] values = LayoutState.values();
        	final int layoutStateIndex = savedInstanceState.getInt("layoutStateIndex");
        	if (layoutStateIndex>=0 && layoutStateIndex<values.length)
        		layoutState = values[layoutStateIndex];
        }
        
        setLayoutState(layoutState);
    }
    
    @Override
    protected void onSaveInstanceState(Bundle outState) {
    	super.onSaveInstanceState(outState);
    	outState.putInt("layoutState", mLayoutState.ordinal());
    }
    
    private void setLayoutState(LayoutState state) {
    	switch (state) {
		case LOADING:
			mViewComplete.setVisibility(View.GONE);
			mViewLoading.setVisibility(View.VISIBLE);
			Log.e("", "LOADING");
			break;
		case COMPLETE:
			mViewComplete.setVisibility(View.VISIBLE);
			mViewLoading.setVisibility(View.GONE);
			Log.e("", "COMPLETE");
			break;
		default:
			mViewComplete.setVisibility(View.GONE);
			mViewLoading.setVisibility(View.GONE);
			Log.e("", "DEFAULT");
			break;
		}
    	mLayoutState = state;
    }
    
    //TODO this method sucks... use threads
    private class LoadUrlAsyncTask extends AsyncTask<Object, Void, HttpResponse> {
    	private AndroidSecureHttpClient mHttpsClient;
    	@Override
    	protected void onPreExecute() {
    		setLayoutState(LayoutState.LOADING);
    	}
    	
		@Override
		protected HttpResponse doInBackground(Object... params) {
			assert(params!=null && params.length==2 && 
					params[0] instanceof AndroidSecureHttpClient && 
					params[1] instanceof String);
			
			mHttpsClient = (AndroidSecureHttpClient) params[0];
			
			HttpResponse res = null;
			
			HttpPost post = new HttpPost((String) params[1]);
			//post.setHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13");
			//post.setHeader("Accept", "text/html,application/xml," + "application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
			//post.setHeader("Content-Type", "application/x-www-form-urlencoded");
			//post.setHeader("Connection", "Keep-Alive");
			
			try {
				res = mHttpsClient.execute(post);
			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SSLException e) {
				final X509Certificate[] chain = CertificateNotAcceptedException.getLastChain(); 
				if (chain!=null) {
					runOnUiThread(new Runnable() {
						@Override
						public void run() {
							final Context context = AndroidSecureHttpClientExampleActivity.this;
							// Create user view describing new certificate
							TextView view = new TextView(context);
							StringBuffer chainInfo = new StringBuffer(100);
			                for (int i = 0; i < chain.length; i++) {
			                    chainInfo.append("Certificate chain[" + i + "]:\n");
			                    chainInfo.append("Subject: " + chain[i].getSubjectDN().toString() + "\n");
			                    chainInfo.append("Issuer: " + chain[i].getIssuerDN().toString() + "\n");
			                }
							view.setText(chainInfo);
							// Create alert dialog enabling user interaction
							new AlertDialog.Builder(context)
						    .setTitle("Confirm Certificate")
						    .setMessage("Import unrecognized certificate?")
						    .setView(view)
						    .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
						        public void onClick(DialogInterface dialog, int whichButton) {
						            try {
										mHttpsClient.getTrustManager().addCertificateChain(chain);
										// TODO Auto-retry HTTPS post
									} catch (CertificateException e) {
										// TODO Auto-generated catch block
										e.printStackTrace();
									}
						        }
						    }).setNegativeButton("Deny", new DialogInterface.OnClickListener() {
						        public void onClick(DialogInterface dialog, int whichButton) {
						            // Do nothing.
						        }
						    }).show();
						}
					});
				}
				e.printStackTrace();
				//TODO Inform UI thread that the request uses an unauthorized certificate
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				mHttpsClient.close();
			}
			if (res!=null)
				Log.e("", "Response status line: " + res.getStatusLine());
			else
				Log.e("", "Gettting response from host failed");
			return res;
		}
    	
		@Override
		protected void onPostExecute(HttpResponse result) {
			final TextView view = (TextView)findViewById(R.id.textContent);
			if (view!=null) {
				if (result!=null) {
					String resultString = null;
					try {
						resultString = EntityUtils.toString(result.getEntity());
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					view.setText("Result: \n" + resultString);
				} else {
					view.setText("Certificate not in keystore!");
				}
				setLayoutState(LayoutState.COMPLETE);
			}
		}
    }
}